package com.paziy.notes.core;

import com.paziy.notes.core.notes.NoteValue;

/**
 * Time signature of composition.
 *
 * @author thecederick@gmail.com (Paziy Evgeniy)
 * @version 0.5
 * @since 1.0 (26.11.13 11:30)
 */
public class TimeSignature {

    //todo must be saved to some data holder like default values maybe xlm in resource folder
    /**
     * Default value of beats. Used in default constructor.
     */
    protected static final byte DEFAULT_BEATS_PER_BAR = 4;

    /**
     * Default value of base. Used in default constructor.
     */
    protected static final NoteValue DEFAULT_BASE_PULSE = NoteValue.Crotchet;

    /**
     * Min allowed value for beats. Used in checkBeats method
     */
    protected static final byte MIN_VALUE_OF_BEATS = 1;

    /**
     * Max allowed value for beats. Used in checkBeats method
     */
    protected static final byte MAX_VALUE_OF_BEATS = 64;

    private byte beatsPerBar;
    private NoteValue basePulse;

    /**
     * Default constructor initializes fields by default values
     */
    public TimeSignature() {
        beatsPerBar = DEFAULT_BEATS_PER_BAR;
        basePulse = DEFAULT_BASE_PULSE;
    }

    /**
     * Creates new Time signature
     *
     * @param beats count of beats per tact
     * @param base base of beats
     */
    public TimeSignature(byte beats, NoteValue base) {
        checkBeats(beats);
        checkBase(base);

        beatsPerBar = beats;
        basePulse = base;
    }

    /**
     * Getter for instance variable beatsPerBar
     *
     * @return beats per bar
     */
    public byte getBeats() {
        return beatsPerBar;
    }

    /**
     * Getter for instance variable basePulse
     *
     * @return base pulse in music
     */
    public NoteValue getBase() {
        return basePulse;
    }

    /**
     * Set new count of beats per bar
     *
     * @param beats new count of bets
     */
    public void setBeats(byte beats) {
        checkBeats(beats);

        beatsPerBar = beats;
    }

    /**
     * Set new count of base beats music pulse
     *
     * @param base new base value
     */
    public void setBase(NoteValue base) {
        checkBase(base);

        basePulse = base;
    }

    /**
     * Method checks value of beats
     *
     * @param beats the top number of Time Signature
     */
    private static void checkBeats(byte beats) {
        if (beats < MIN_VALUE_OF_BEATS || beats > MAX_VALUE_OF_BEATS) {
            throw new RuntimeException("Wrong value of Beats Time Signature: " + beats);
        }
    }

    /**
     * Method checks value of base
     *
     * @param base the bottom number of Time Signature
     */
    private static void checkBase(NoteValue base) {
        if (base == null) {
            throw new RuntimeException(new NullPointerException("Null value of Base Time Signature"));
        }
    }
}
